library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ────────────────────────────────── tidyverse 1.3.0 ──
✓ ggplot2 3.3.2     ✓ purrr   0.3.4
✓ tibble  3.0.4     ✓ dplyr   1.0.2
✓ tidyr   1.1.2     ✓ stringr 1.4.0
✓ readr   1.4.0     ✓ forcats 0.5.0
── Conflicts ───────────────────────────────────── tidyverse_conflicts() ──
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(lubridate)

Attaching package: ‘lubridate’

The following objects are masked from ‘package:base’:

    date, intersect, setdiff, union
library(modelr)
library(broom)

Attaching package: ‘broom’

The following object is masked from ‘package:modelr’:

    bootstrap

Modeller

Leser inn data

arblos <- read_csv("data/al9914m.csv")

── Column specification ───────────────────────────────────────────────────
cols(
  knr = col_character(),
  knavn = col_character(),
  aar = col_double(),
  mnd = col_double(),
  al_Menn = col_double(),
  al_Kvinner = col_double(),
  alp_Menn = col_double(),
  alp_Kvinner = col_double(),
  alp_15_74 = col_double(),
  alp_15_29 = col_double(),
  alp_30_74 = col_double()
)
bef <- read_csv("data/bef9914MK.csv")

── Column specification ───────────────────────────────────────────────────
cols(
  knr = col_character(),
  knavn = col_character(),
  aar = col_double(),
  bef_K_0_14 = col_double(),
  bef_K_15_29 = col_double(),
  bef_K_30_74 = col_double(),
  bef_K_75_105 = col_double(),
  bef_M_0_14 = col_double(),
  bef_M_15_29 = col_double(),
  bef_M_30_74 = col_double(),
  bef_M_75_105 = col_double(),
  bef_MK_0_14 = col_double(),
  bef_MK_15_29 = col_double(),
  bef_MK_30_74 = col_double(),
  bef_MK_75_105 = col_double()
)

Modeller med data fra bef (befolkning)

dim(arblos)
[1] 77330    11
dim(bef)
[1] 6688   15
names(bef)
 [1] "knr"           "knavn"         "aar"           "bef_K_0_14"   
 [5] "bef_K_15_29"   "bef_K_30_74"   "bef_K_75_105"  "bef_M_0_14"   
 [9] "bef_M_15_29"   "bef_M_30_74"   "bef_M_75_105"  "bef_MK_0_14"  
[13] "bef_MK_15_29"  "bef_MK_30_74"  "bef_MK_75_105"
names(arblos)
 [1] "knr"         "knavn"       "aar"         "mnd"         "al_Menn"    
 [6] "al_Kvinner"  "alp_Menn"    "alp_Kvinner" "alp_15_74"   "alp_15_29"  
[11] "alp_30_74"  

Arbeidsledighetsprosenten blir beregnet som: arbl% = antall arb. ledige/arbeidsstyrken. Arbeidsstyrken er her dem man anser egnet for arbeid dvs. uføretrygdete etc. er trukket ut. Arbeidsstyren i en aldesrkategori er derfor langt mindre enn befolkningen i den tilsvarende alderskategorien.

Dessverre kjenne vi ikke arbeidsstyrken, men vi kan beregne den vha.: arbeidsstyrken = antall arb. ledige/arb. ledighetsprosent.

arblos <- arblos %>% 
    mutate(
        wf_K = (al_Kvinner/alp_Kvinner)*100,
        wf_M = (al_Menn/alp_Menn)*100,
        wf_KM = wf_K + wf_M
    )
arblos

Arbeidsstyrken

Når befolkningen øker vil også arbeidsstyrken øke. Det er derfor mer naturlig å se på arbeidsstyrken relativt til delen av befolkningen som er i yrkesaktiv alder (15-74 år her).

names(bef)
 [1] "knr"           "knavn"         "aar"           "bef_K_0_14"   
 [5] "bef_K_15_29"   "bef_K_30_74"   "bef_K_75_105"  "bef_M_0_14"   
 [9] "bef_M_15_29"   "bef_M_30_74"   "bef_M_75_105"  "bef_MK_0_14"  
[13] "bef_MK_15_29"  "bef_MK_30_74"  "bef_MK_75_105"

Vi skal starte med å lage et datasett med arbeidsstyrken (wf) for hele landet samlet, men fordelt på de tre kategorien kvinner, menn og kvinner + menn.

Bruk data for januar hvert år til å beregne wf på landsbasis

# årlige data landet samlet
wf <- arblos %>% 
    filter(mnd == 1) %>% 
    group_by(aar) %>% 
    summarise(
        wf_K = sum(wf_K, na.rm = TRUE),
        wf_M = sum(wf_M, na.rm = TRUE),
        wf_KM = wf_K + wf_M
    )
`summarise()` ungrouping output (override with `.groups` argument)
dim(wf)
[1] 16  4
wf
dim(wf)
[1] 16  4
names(wf)
[1] "aar"   "wf_K"  "wf_M"  "wf_KM"

Summer de ulike årskategoriene for de to kjønnene og menn+kvinner for å finne total befolkning de ulike årene. Bruk mutate til å lage de nye variablene.

 bef <- bef %>% 
  mutate(
    bef_K = bef_K_0_14 + bef_K_15_29 + bef_K_30_74 + bef_K_75_105,
    bef_M = bef_M_0_14 + bef_M_15_29 + bef_M_30_74 + bef_M_75_105,
    bef_KM = bef_K + bef_M)
dim(bef)
[1] 6688   18
names(bef)
 [1] "knr"           "knavn"         "aar"           "bef_K_0_14"   
 [5] "bef_K_15_29"   "bef_K_30_74"   "bef_K_75_105"  "bef_M_0_14"   
 [9] "bef_M_15_29"   "bef_M_30_74"   "bef_M_75_105"  "bef_MK_0_14"  
[13] "bef_MK_15_29"  "bef_MK_30_74"  "bef_MK_75_105" "bef_K"        
[17] "bef_M"         "bef_KM"       

Legg befolkningsdata varaiablene bef_K, bef_M, bef_KM til wf. Husk at de må aggregeres for hele landet (group_by() og så summarise() før de «joines»). Bruk tilslutt mutate() make_date() for å lage en ny variabel år som er en date, dvs aar + month=1L + day=1L.

wf_hjelp <- bef %>%
  group_by(aar) %>%
  summarise(bef_K = sum(bef_K),
            bef_M = sum(bef_M),
            bef_KM = sum(bef_KM))
`summarise()` ungrouping output (override with `.groups` argument)
wf <- left_join(wf, wf_hjelp)
Joining, by = "aar"
wf <- wf %>%
  select(aar, bef_K, bef_M, bef_KM, wf_K, wf_M, wf_KM) %>%
  mutate(år = make_date(aar, month = 1L, day = 1L))

rm(wf_hjelp)

Da skal du få

wf

Vi vil nå se på arbeidsstyrke relativt til befolkning på landsbasis, dvs. wf_K/bef_K etc. Plot dataen vha. geom_line() for de tre kategoriene. Bruk år som x-variabel.

wf %>% 
    ggplot(wf, mapping = aes(x = år)) +
  geom_line(mapping = aes(y = wf_K/bef_K), color = "red") +
  geom_line(mapping = aes(y = wf_M/bef_M, color = "blue"), color = "darkblue") +
  geom_line(mapping = aes(y = wf_KM/bef_KM), color = "black") +
  ggtitle("Arbeidsstyrke relativt til befolkning. Menn blå, kvinner rød og totalt svart.") +
  theme(legend.position = "none")

Hvordan kan pukkelen rett før 2010 forklares?

Det kan skyldes at verdensøkonomien gikk bra, og at det i 2008/2009 var en finanskrise i verden som påvirket økonomien og næringene.

names(arblos)
 [1] "knr"         "knavn"       "aar"         "mnd"         "al_Menn"    
 [6] "al_Kvinner"  "alp_Menn"    "alp_Kvinner" "alp_15_74"   "alp_15_29"  
[11] "alp_30_74"   "wf_K"        "wf_M"        "wf_KM"      

Vi vil nå generere dat for arbeidsstyrken på fylkesbasis. Husk at de to første sifferene i knr angir fylket en kommune ligger i. Bruk dataene i arblos til å finne arbeidsstyrken på fylkesbasis (wf_f). Start med å bruke mutate() til å lage en ny variabel fylke. Grupper så og finn wf_K_f, wf_M_f og wf_KM_f vha. summarise(). Lag til slutt en ny variabel år som en date. Velg til slutt de relevante variabelen vha. select().

# årlige data per fylke
wf_f <- arblos %>% 
    mutate(
        fylke = substr(knr, start = 1, stop = 2)
    ) %>% 
    group_by(aar, mnd, fylke) %>% 
    summarise(
        wf_K_f = sum(wf_K, na.rm = TRUE),
        wf_M_f = sum(wf_M, na.rm = TRUE),
        wf_KM_f = wf_K_f + wf_M_f
    ) %>% 
    mutate(år = make_date(aar, mnd, day=1L)) %>% 
    select(aar, mnd, år, fylke, wf_K_f, wf_M_f, wf_KM_f)
`summarise()` regrouping output by 'aar', 'mnd' (override with `.groups` argument)

Vi skal nå ha en tibble wf_f som ser slik ut:

print(wf_f, n = 5)

Lag også en ny tibble bef_f fra bef som inneholder befolkningen i hvert fylke hvert år.

bef_f <- bef %>% 
      mutate(
        fylke = substr(knr, start = 1, stop = 2)
    ) %>% 
    group_by(aar, fylke) %>% 
    summarise(
        bef_K_f = sum(bef_K, na.rm = TRUE),
        bef_M_f = sum(bef_M, na.rm = TRUE),
        bef_KM_f = bef_K_f + bef_M_f
    ) %>% 
    select(aar, fylke, bef_K_f, bef_M_f, bef_KM_f)
`summarise()` regrouping output by 'aar' (override with `.groups` argument)
bef_f

Lag til slutt tibble-en wf_f_bef som innholde arbeidsstyrke (wf-f) og befolkning (bef-f) på fylkesnivå for hvert år.

wf_f_bef <- wf_f %>% 
  right_join(bef_f) %>%
  arrange(fylke, aar, mnd)
Joining, by = c("aar", "fylke")

Da skal wf_f_bef se slik ut:

print(arrange(wf_f_bef, fylke, aar, mnd))

Plot nå arbeidsstyrke relativt til befolkning vha. geom_line()

# kvinner og menn
wf_f_bef %>%
  ggplot() +
  geom_line(wf_f_bef, mapping = aes(x = år,
                                    y = wf_KM_f/bef_KM_f,
                                    color = fylke)) +
  theme(legend.position = "bottom")

Lage regioner

Alle fylkene blir litt rotete så vi definerer istedet seks regioner vha. case_when() og lager en ny tibble wf_r fra wf_f_bef.

# region
wf_r <- wf_f_bef %>% 
    mutate(
         dato = ymd(paste(aar, mnd, "01", sep = "-")),
        region = case_when(
            as.numeric(fylke) == 3 ~ "Oslo",
            as.numeric(fylke) %in% c(1:2, 4:8) ~ "Østlandet",
            as.numeric(fylke) %in% c(9, 10) ~ "Sørlandet",
            as.numeric(fylke) %in% c(11, 12, 14, 15) ~ "Vestlandet",
            as.numeric(fylke) %in% c(16, 17) ~ "Trøndelag",
            as.numeric(fylke) %in% c(18, 19, 20) ~ "Nord-Norge"
        )
    ) %>% 
    group_by(dato, region) %>% 
    summarise(
        wf_K_r = sum(wf_K_f, na.rm = TRUE),
        wf_M_r = sum(wf_M_f, na.rm = TRUE),
        wf_KM_r = wf_K_r + wf_M_r,
        bef_K_r = sum(bef_K_f, na.rm = TRUE),
        bef_M_r = sum(bef_M_f, na.rm = TRUE),
        bef_KM_r = bef_K_r + bef_M_r
    ) %>% 
    select(dato, region, wf_K_r, wf_M_r, wf_KM_r, bef_K_r, bef_M_r, bef_KM_r)
`summarise()` regrouping output by 'dato' (override with `.groups` argument)

Plot nå for regionene wf_KM_r/bef_KM_r, både vha. geom_line() og geom_smooth(). La farge vise regionene. Sett denne i ggplot() slik at det gjelder for både geom_line() og geom_smooth(). Sett i tillegg alpha = 0.5 for geom_line() og se = FALSE for geom_smooth(). Legg til theme(legend.position = “bottom”) til slutt for å få legend under plottet.

# kvinner og menn
wf_r %>% 
  ggplot(wf_r, mapping = aes(x = dato, 
                             y = wf_KM_r/bef_KM_r,
                             color = region)) +
  geom_line(alpha = 0.5) +
  geom_smooth(se = FALSE) +
  theme(legend.position = "bottom") +
  ggtitle("Arbeidsstyrkens andel av befolkningen for regionene.")

Lag tilsvarende plot for kvinner.

# kvinner
wf_r %>% 
  ggplot(wf_r, mapping = aes(x = dato, 
                             y = wf_K_r/bef_K_r,
                             color = region)) +
  geom_line(alpha = 0.5) +
  geom_smooth(se = FALSE) +
  theme(legend.position = "bottom") +
  ggtitle("Arbeidsstyrkens andel av befolkningen for kvinner per region.")

Lag tilsvarende plot for menn

# menn
wf_r %>% 
  ggplot(wf_r, mapping = aes(x = dato, 
                             y = wf_M_r/bef_M_r,
                             color = region)) +
  geom_line(alpha = 0.5) +
  geom_smooth(se = FALSE) +
  theme(legend.position = "bottom") +
  ggtitle("Arbeidsstyrkens andel av befolkningen for menn per region.")

Forlar kort den generelle utviklingen i arbeidsstyrken. Hva er det som «redder oss»?

For kvinnene kan en se at det er en jevnt økende trend at flere kvinner fra arbeidsstyrken jobber. Det kan skyldes flere grunner, men en av dem kan være kampen for likestilling og at kvinnene skal aktivt delta i jobbmarkedene og ikke slik de gjorde før. En kan se at de har en liten utflating av kurven i 2007/2008 og den faller litt etter 2011. Den første utflatingen kan skyldes finanskrisen og det som førte med der, mens i 2011 kan det skyldes andre ting. En kan se at hos menn synker kurven i alle regionene, i noen regioner mer enn andre. Litt fargesvak, men tror det er Oslo som redder oss. Eventuelt Vestlandet.

nest() arblos

Da skal vi jobbe direkte med arbeidsløshet og lage lineære modeller for hver av de 418 kommunene. Modellen vi skal lage er på ingen måte perfekt. Vi er interessert i selve teknikken med å organisere dataene og kjøre modeller på mange subsett av dataene (her for hver kommune).

Vi vil se på en modell der vi forklarer arbeidsstyrken i en kommune vha. ungdomsledighet og ledighet blant litt eldre arbeidstakere (30-74 år). En hypotese er at vi vil se en negativ sammenheng mellom ungdomsledighet og arbeidsstyrken. De unge flytter hvis det ikke er jobb.

Vi starter med å gruppere på kommune og nest-e dataene.

arblos_by_knr <- arblos %>% 
    group_by(knr, knavn) %>% 
    nest()
print(arblos_by_knr, n = 4)
arblos_by_knr$data[[1]]

Vi har nå en tibble med data for hver kommune inne i tibble-en arblos_by_knr.

Skriv en funksjon som kjører den lineære modellen wf_KM ~ alp_15_29 + alp_30_74 på en input dataframe a_df. Kall funksjonen mod1 (i magel på noe bedre navn).

mod1 <- function(a_df){
  lm(wf_KM ~ alp_15_29 + alp_30_74, data = a_df)}

KJøre så modellen vha. funksjonen mod1 på data i arblos_by_knr, og lag en list-column i arblos_by_knr som inneholder modellen. Kjør også tidy og glance fra broom på modellene for å få hhv. koeffisienter og ulike summary av modellen. Lagre resultatene i hhv. mod1_arblos, mod1_arblos_coef og mod1_arblos_sum (i siste er sum forkortelse for summary)

arblos_by_knr <- arblos_by_knr %>% 
    mutate(mod1_arblos = map(data, .f = mod1)) %>%
    mutate(mod1_arblos_coef = map(mod1_arblos, .f = tidy)) %>% 
    mutate(mod1_arblos_sum = map(mod1_arblos, .f = glance))
arblos_by_knr[arblos_by_knr$knr == "0441",][[3]]
[[1]]
NA

arblos_by_knr skal nå se ut slik:

arblos_by_knr

Kommunestørrelse

Vi lager oss så en ny kategori variabel for kommunestørrelse.

kom_str <- bef %>% 
    filter(aar == 2014) %>% 
    mutate(
        k_str = case_when(
            bef_KM <= 2500 ~ "Svært liten",
            bef_KM > 2500 & bef_KM <= 6000 ~ "Liten",
            bef_KM > 6000 & bef_KM <= 20000 ~ "Middels",
            bef_KM > 20000 & bef_KM <= 60000 ~ "Stor",
            bef_KM > 60000 & bef_KM <= 1000000 ~ "Svært stor"
        )
    ) %>% 
    select(knr, knavn, bef_KM, k_str)
head(kom_str)

Pakker ut og henter model karakteristika

Bruk så unnest() til å pakke ut mod1_arblos_coef og mod1_arblos_coef (husk at de to må stå i en c() og ha anførselstegn). Plukk ut variablene knr, knavn, term, estimate, std.error, p.value…9, adj.r.squared og legg resultatet i mod_arbl_re.

#modell arbeidsløse resultat
mod_arbl_re <- arblos_by_knr %>% 
  unnest(c("mod1_arblos_coef", "mod1_arblos_sum"), names_repair = "universal") %>% 
  select(knr, knavn, term, estimate, std.error, p.value...9, adj.r.squared)
New names:
* statistic -> statistic...8
* p.value -> p.value...9
* statistic -> statistic...13
* p.value -> p.value...14

Du skal da ha noe som ser slik ut:

print(mod_arbl_re, n = 10)

Slå sammen kom_str og mod_arbl_re vha. left_join(). Kall resultatet for kom_str_mod.

kom_str_mod <- mod_arbl_re %>% 
    left_join(kom_str, by = c("knr", "knavn")) 

Da skal du ha noe som ser slik ut:

print(kom_str_mod, n = 5)

Vi plotter koeffisientene som er signifikante og lar farge vise kommune størrelse. Tar vekk ekstreme estimat.

kom_str_mod %>% 
    filter(term == "alp_15_29") %>% 
    filter(estimate > -500 & estimate < 500 ) %>%
    filter(p.value...9 < 0.05) %>% 
    ggplot(mapping = aes(
        x = estimate,
        y = p.value...9,
        colour = k_str
        )
        ) +
    geom_point()

Lag tilsvarende plot for alp_30_74.

kom_str_mod %>% 
    filter(term == "alp_30_74") %>% 
    filter(estimate > -500 & estimate < 500 ) %>%
    filter(p.value...9 < 0.05) %>% 
    ggplot(mapping = aes(
        x = estimate,
        y = p.value...9,
        colour = k_str
        )
        ) +
    geom_point()

Hvor mange har vi?

kom_str_mod %>% 
    filter(term == "alp_15_29") %>% 
    group_by(k_str) %>% 
    summarise(n = n())
`summarise()` ungrouping output (override with `.groups` argument)
kom_str_mod %>% 
    filter(term == "alp_15_29") %>% 
    filter(estimate > - 500 & estimate < 500 ) %>%
    filter(p.value...9 < 0.05) %>% 
    group_by(k_str) %>% 
    summarise(n = n())
`summarise()` ungrouping output (override with `.groups` argument)
kom_str_mod %>% 
    filter(term == "alp_30_74") %>% 
    filter(estimate > - 500 & estimate < 500 ) %>%
    filter(p.value...9 < 0.05) %>% 
    group_by(k_str) %>% 
    summarise(n = n())
`summarise()` ungrouping output (override with `.groups` argument)
kom_str_mod %>% 
    filter(term == "alp_15_29") %>% 
    filter(p.value...9 < 0.05) %>% 
    group_by(k_str) %>% 
    summarise(mean_15_29 = mean(estimate))
`summarise()` ungrouping output (override with `.groups` argument)
kom_str_mod %>% 
    filter(term == "alp_30_74") %>% 
    filter(p.value...9 < 0.05) %>% 
    group_by(k_str) %>% 
    summarise(mean_30_74 = mean(estimate))
`summarise()` ungrouping output (override with `.groups` argument)
kom_str_mod %>% 
    filter(term == "alp_15_29") %>% 
    filter(p.value...9 < 0.05) %>% 
    group_by(k_str) %>% 
    summarise(n = n())
`summarise()` ungrouping output (override with `.groups` argument)
kom_str_mod %>% 
    filter(term == "alp_30_74") %>% 
    filter(p.value...9 < 0.05) %>% 
    group_by(k_str) %>% 
    summarise(n = n())
`summarise()` ungrouping output (override with `.groups` argument)

I litt over 50% av kommunene, hovedsaklig de små, ser modellen ut til virke. Kanskje noe å bygge videre på.

#siste
LS0tCnRpdGxlOiAiQXNzaWdubWVudCA0IgpvdXRwdXQ6CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAotLS0KCmBgYHtyIHNldHVwfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkobW9kZWxyKQpsaWJyYXJ5KGJyb29tKQpgYGAKCiMgTW9kZWxsZXIKCiMjIExlc2VyIGlubiBkYXRhCgpgYGB7cn0KYXJibG9zIDwtIHJlYWRfY3N2KCJkYXRhL2FsOTkxNG0uY3N2IikKYmVmIDwtIHJlYWRfY3N2KCJkYXRhL2JlZjk5MTRNSy5jc3YiKQpgYGAKCiMjIE1vZGVsbGVyIG1lZCBkYXRhIGZyYSAqYmVmKiAoYmVmb2xrbmluZykKCmBgYHtyfQpkaW0oYXJibG9zKQpkaW0oYmVmKQpgYGAKCgpgYGB7cn0KbmFtZXMoYmVmKQpgYGAKCmBgYHtyfQpuYW1lcyhhcmJsb3MpCmBgYAoKQXJiZWlkc2xlZGlnaGV0c3Byb3NlbnRlbiBibGlyIGJlcmVnbmV0IHNvbTogYXJibCUgPSBhbnRhbGwgYXJiLiBsZWRpZ2UvYXJiZWlkc3N0eXJrZW4uIEFyYmVpZHNzdHlya2VuIGVyIGhlciBkZW0gbWFuIGFuc2VyIGVnbmV0IGZvciBhcmJlaWQgZHZzLiB1ZsO4cmV0cnlnZGV0ZSBldGMuIGVyIHRydWtrZXQgdXQuIEFyYmVpZHNzdHlyZW4gaSBlbiBhbGRlc3JrYXRlZ29yaSBlciBkZXJmb3IgbGFuZ3QgbWluZHJlIGVubiBiZWZvbGtuaW5nZW4gaSBkZW4gdGlsc3ZhcmVuZGUgYWxkZXJza2F0ZWdvcmllbi4KCkRlc3N2ZXJyZSBramVubmUgdmkgaWtrZSBhcmJlaWRzc3R5cmtlbiwgbWVuIHZpIGthbiBiZXJlZ25lIGRlbiB2aGEuOiAKYXJiZWlkc3N0eXJrZW4gPSBhbnRhbGwgYXJiLiBsZWRpZ2UvYXJiLiBsZWRpZ2hldHNwcm9zZW50LgoKYGBge3J9CmFyYmxvcyA8LSBhcmJsb3MgJT4lIAogICAgbXV0YXRlKAogICAgICAgIHdmX0sgPSAoYWxfS3Zpbm5lci9hbHBfS3Zpbm5lcikqMTAwLAogICAgICAgIHdmX00gPSAoYWxfTWVubi9hbHBfTWVubikqMTAwLAogICAgICAgIHdmX0tNID0gd2ZfSyArIHdmX00KICAgICkKYGBgCgpgYGB7cn0KYXJibG9zCmBgYAoKIyMgQXJiZWlkc3N0eXJrZW4KCk7DpXIgYmVmb2xrbmluZ2VuIMO4a2VyIHZpbCBvZ3PDpSBhcmJlaWRzc3R5cmtlbiDDuGtlLiBEZXQgZXIgZGVyZm9yIG1lciBuYXR1cmxpZyDDpSBzZSBww6UgYXJiZWlkc3N0eXJrZW4gcmVsYXRpdnQgdGlsIGRlbGVuIGF2IGJlZm9sa25pbmdlbiBzb20gZXIgaSB5cmtlc2FrdGl2IGFsZGVyICgxNS03NCDDpXIgaGVyKS4KCmBgYHtyfQpuYW1lcyhiZWYpCmBgYAoKVmkgc2thbCBzdGFydGUgbWVkIMOlIGxhZ2UgZXQgZGF0YXNldHQgbWVkIGFyYmVpZHNzdHlya2VuICh3ZikgZm9yIGhlbGUgbGFuZGV0IHNhbWxldCwgbWVuIGZvcmRlbHQgcMOlIGRlIHRyZSBrYXRlZ29yaWVuIGt2aW5uZXIsIG1lbm4gb2cga3Zpbm5lciArIG1lbm4uCgpCcnVrIGRhdGEgZm9yIGphbnVhciBodmVydCDDpXIgdGlsIMOlIGJlcmVnbmUgd2YgcMOlIGxhbmRzYmFzaXMKCmBgYHtyfQojIMOlcmxpZ2UgZGF0YSBsYW5kZXQgc2FtbGV0CndmIDwtIGFyYmxvcyAlPiUgCiAgICBmaWx0ZXIobW5kID09IDEpICU+JSAKICAgIGdyb3VwX2J5KGFhcikgJT4lIAogICAgc3VtbWFyaXNlKAogICAgICAgIHdmX0sgPSBzdW0od2ZfSywgbmEucm0gPSBUUlVFKSwKICAgICAgICB3Zl9NID0gc3VtKHdmX00sIG5hLnJtID0gVFJVRSksCiAgICAgICAgd2ZfS00gPSB3Zl9LICsgd2ZfTQogICAgKQpkaW0od2YpCndmCmBgYAoKYGBge3J9CmRpbSh3ZikKbmFtZXMod2YpCmBgYAoKU3VtbWVyIGRlIHVsaWtlIMOlcnNrYXRlZ29yaWVuZSBmb3IgZGUgdG8ga2rDuG5uZW5lIG9nIG1lbm4ra3Zpbm5lciBmb3Igw6UgZmlubmUgdG90YWwgYmVmb2xrbmluZyBkZSB1bGlrZSDDpXJlbmUuIEJydWsgbXV0YXRlIHRpbCDDpSBsYWdlIGRlIG55ZSB2YXJpYWJsZW5lLgoKYGBge3J9CiBiZWYgPC0gYmVmICU+JSAKICBtdXRhdGUoCiAgICBiZWZfSyA9IGJlZl9LXzBfMTQgKyBiZWZfS18xNV8yOSArIGJlZl9LXzMwXzc0ICsgYmVmX0tfNzVfMTA1LAogICAgYmVmX00gPSBiZWZfTV8wXzE0ICsgYmVmX01fMTVfMjkgKyBiZWZfTV8zMF83NCArIGJlZl9NXzc1XzEwNSwKICAgIGJlZl9LTSA9IGJlZl9LICsgYmVmX00pCmBgYAoKYGBge3J9CmRpbShiZWYpCm5hbWVzKGJlZikKYGBgCgpMZWdnIGJlZm9sa25pbmdzZGF0YSB2YXJhaWFibGVuZSBiZWZfSywgYmVmX00sIGJlZl9LTSB0aWwgd2YuIEh1c2sgYXQgZGUgbcOlIGFnZ3JlZ2VyZXMgZm9yIGhlbGUgbGFuZGV0IChncm91cF9ieSgpIG9nIHPDpSBzdW1tYXJpc2UoKSBmw7hyIGRlIMKram9pbmVzwrspLiBCcnVrIHRpbHNsdXR0IG11dGF0ZSgpIG1ha2VfZGF0ZSgpIGZvciDDpSBsYWdlIGVuIG55IHZhcmlhYmVsIMOlciBzb20gZXIgZW4gZGF0ZSwgZHZzIGFhciArIG1vbnRoPTFMICsgZGF5PTFMLgoKYGBge3J9CndmX2hqZWxwIDwtIGJlZiAlPiUKICBncm91cF9ieShhYXIpICU+JQogIHN1bW1hcmlzZShiZWZfSyA9IHN1bShiZWZfSyksCiAgICAgICAgICAgIGJlZl9NID0gc3VtKGJlZl9NKSwKICAgICAgICAgICAgYmVmX0tNID0gc3VtKGJlZl9LTSkpCndmIDwtIGxlZnRfam9pbih3Ziwgd2ZfaGplbHApCndmIDwtIHdmICU+JQogIHNlbGVjdChhYXIsIGJlZl9LLCBiZWZfTSwgYmVmX0tNLCB3Zl9LLCB3Zl9NLCB3Zl9LTSkgJT4lCiAgbXV0YXRlKMOlciA9IG1ha2VfZGF0ZShhYXIsIG1vbnRoID0gMUwsIGRheSA9IDFMKSkKCnJtKHdmX2hqZWxwKQpgYGAKCkRhIHNrYWwgZHUgZsOlCgpgYGB7cn0Kd2YKYGBgClZpIHZpbCBuw6Ugc2UgcMOlIGFyYmVpZHNzdHlya2UgcmVsYXRpdnQgdGlsIGJlZm9sa25pbmcgcMOlIGxhbmRzYmFzaXMsIGR2cy4gd2ZfSy9iZWZfSyBldGMuClBsb3QgZGF0YWVuIHZoYS4gZ2VvbV9saW5lKCkgZm9yIGRlIHRyZSBrYXRlZ29yaWVuZS4gQnJ1ayDDpXIgc29tIHgtdmFyaWFiZWwuCgpgYGB7cn0Kd2YgJT4lIAogICAgZ2dwbG90KHdmLCBtYXBwaW5nID0gYWVzKHggPSDDpXIpKSArCiAgZ2VvbV9saW5lKG1hcHBpbmcgPSBhZXMoeSA9IHdmX0svYmVmX0spLCBjb2xvciA9ICJyZWQiKSArCiAgZ2VvbV9saW5lKG1hcHBpbmcgPSBhZXMoeSA9IHdmX00vYmVmX00sIGNvbG9yID0gImJsdWUiKSwgY29sb3IgPSAiZGFya2JsdWUiKSArCiAgZ2VvbV9saW5lKG1hcHBpbmcgPSBhZXMoeSA9IHdmX0tNL2JlZl9LTSksIGNvbG9yID0gImJsYWNrIikgKwogIGdndGl0bGUoIkFyYmVpZHNzdHlya2UgcmVsYXRpdnQgdGlsIGJlZm9sa25pbmcuIE1lbm4gYmzDpSwga3Zpbm5lciByw7hkIG9nIHRvdGFsdCBzdmFydC4iKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKCkh2b3JkYW4ga2FuIHB1a2tlbGVuIHJldHQgZsO4ciAyMDEwIGZvcmtsYXJlcz8KCkRldCBrYW4gc2t5bGRlcyBhdCB2ZXJkZW5zw7hrb25vbWllbiBnaWtrIGJyYSwgb2cgYXQgZGV0IGkgMjAwOC8yMDA5IHZhciBlbiBmaW5hbnNrcmlzZSBpIHZlcmRlbiBzb20gcMOldmlya2V0IMO4a29ub21pZW4gb2cgbsOmcmluZ2VuZS4gCgpgYGB7cn0KbmFtZXMoYXJibG9zKQpgYGAKClZpIHZpbCBuw6UgZ2VuZXJlcmUgZGF0IGZvciBhcmJlaWRzc3R5cmtlbiBww6UgZnlsa2VzYmFzaXMuIEh1c2sgYXQgZGUgdG8gZsO4cnN0ZSBzaWZmZXJlbmUgaSBrbnIgYW5naXIgZnlsa2V0IGVuIGtvbW11bmUgbGlnZ2VyIGkuIEJydWsgZGF0YWVuZSBpIGFyYmxvcyB0aWwgw6UgZmlubmUgYXJiZWlkc3N0eXJrZW4gcMOlIGZ5bGtlc2Jhc2lzICh3Zl9mKS4gU3RhcnQgbWVkIMOlIGJydWtlIG11dGF0ZSgpIHRpbCDDpSBsYWdlIGVuIG55IHZhcmlhYmVsIGZ5bGtlLiBHcnVwcGVyIHPDpSBvZyBmaW5uIHdmX0tfZiwgd2ZfTV9mIG9nIHdmX0tNX2YgdmhhLiBzdW1tYXJpc2UoKS4gTGFnIHRpbCBzbHV0dCBlbiBueSB2YXJpYWJlbCDDpXIgc29tIGVuIGRhdGUuIFZlbGcgdGlsIHNsdXR0IGRlIHJlbGV2YW50ZSB2YXJpYWJlbGVuIHZoYS4gc2VsZWN0KCkuCgpgYGB7cn0KIyDDpXJsaWdlIGRhdGEgcGVyIGZ5bGtlCndmX2YgPC0gYXJibG9zICU+JSAKICAgIG11dGF0ZSgKICAgICAgICBmeWxrZSA9IHN1YnN0cihrbnIsIHN0YXJ0ID0gMSwgc3RvcCA9IDIpCiAgICApICU+JSAKICAgIGdyb3VwX2J5KGFhciwgbW5kLCBmeWxrZSkgJT4lIAogICAgc3VtbWFyaXNlKAogICAgICAgIHdmX0tfZiA9IHN1bSh3Zl9LLCBuYS5ybSA9IFRSVUUpLAogICAgICAgIHdmX01fZiA9IHN1bSh3Zl9NLCBuYS5ybSA9IFRSVUUpLAogICAgICAgIHdmX0tNX2YgPSB3Zl9LX2YgKyB3Zl9NX2YKICAgICkgJT4lIAogICAgbXV0YXRlKMOlciA9IG1ha2VfZGF0ZShhYXIsIG1uZCwgZGF5PTFMKSkgJT4lIAogICAgc2VsZWN0KGFhciwgbW5kLCDDpXIsIGZ5bGtlLCB3Zl9LX2YsIHdmX01fZiwgd2ZfS01fZikKYGBgClZpIHNrYWwgbsOlIGhhIGVuIHRpYmJsZSB3Zl9mIHNvbSBzZXIgc2xpayB1dDoKCmBgYHtyfQpwcmludCh3Zl9mLCBuID0gNSkKYGBgCkxhZyBvZ3PDpSBlbiBueSB0aWJibGUgYmVmX2YgZnJhIGJlZiBzb20gaW5uZWhvbGRlciBiZWZvbGtuaW5nZW4gaSBodmVydCBmeWxrZSBodmVydCDDpXIuCgpgYGB7cn0KYmVmX2YgPC0gYmVmICU+JSAKICAgICAgbXV0YXRlKAogICAgICAgIGZ5bGtlID0gc3Vic3RyKGtuciwgc3RhcnQgPSAxLCBzdG9wID0gMikKICAgICkgJT4lIAogICAgZ3JvdXBfYnkoYWFyLCBmeWxrZSkgJT4lIAogICAgc3VtbWFyaXNlKAogICAgICAgIGJlZl9LX2YgPSBzdW0oYmVmX0ssIG5hLnJtID0gVFJVRSksCiAgICAgICAgYmVmX01fZiA9IHN1bShiZWZfTSwgbmEucm0gPSBUUlVFKSwKICAgICAgICBiZWZfS01fZiA9IGJlZl9LX2YgKyBiZWZfTV9mCiAgICApICU+JSAKICAgIHNlbGVjdChhYXIsIGZ5bGtlLCBiZWZfS19mLCBiZWZfTV9mLCBiZWZfS01fZikKYGBgCgpgYGB7cn0KYmVmX2YKYGBgCgpMYWcgdGlsIHNsdXR0IHRpYmJsZS1lbiB3Zl9mX2JlZiBzb20gaW5uaG9sZGUgYXJiZWlkc3N0eXJrZSAod2YtZikgb2cgYmVmb2xrbmluZyAoYmVmLWYpIHDDpSBmeWxrZXNuaXbDpSBmb3IgaHZlcnQgw6VyLgoKYGBge3J9CndmX2ZfYmVmIDwtIHdmX2YgJT4lIAogIHJpZ2h0X2pvaW4oYmVmX2YpICU+JQogIGFycmFuZ2UoZnlsa2UsIGFhciwgbW5kKQpgYGAKCkRhIHNrYWwgd2ZfZl9iZWYgc2Ugc2xpayB1dDoKCmBgYHtyfQpwcmludChhcnJhbmdlKHdmX2ZfYmVmLCBmeWxrZSwgYWFyLCBtbmQpKQpgYGAKUGxvdCBuw6UgYXJiZWlkc3N0eXJrZSByZWxhdGl2dCB0aWwgYmVmb2xrbmluZyB2aGEuIGdlb21fbGluZSgpCgpgYGB7cn0KIyBrdmlubmVyIG9nIG1lbm4Kd2ZfZl9iZWYgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fbGluZSh3Zl9mX2JlZiwgbWFwcGluZyA9IGFlcyh4ID0gw6VyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gd2ZfS01fZi9iZWZfS01fZiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBmeWxrZSkpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKYGBgCgoKIyMjIExhZ2UgcmVnaW9uZXIKCkFsbGUgZnlsa2VuZSBibGlyIGxpdHQgcm90ZXRlIHPDpSB2aSBkZWZpbmVyZXIgaXN0ZWRldCBzZWtzIHJlZ2lvbmVyIHZoYS4gY2FzZV93aGVuKCkKIG9nIGxhZ2VyIGVuIG55IHRpYmJsZSB3Zl9yIGZyYSB3Zl9mX2JlZi4KYGBge3J9CiMgcmVnaW9uCndmX3IgPC0gd2ZfZl9iZWYgJT4lIAogICAgbXV0YXRlKAogICAgICAgICBkYXRvID0geW1kKHBhc3RlKGFhciwgbW5kLCAiMDEiLCBzZXAgPSAiLSIpKSwKICAgICAgICByZWdpb24gPSBjYXNlX3doZW4oCiAgICAgICAgICAgIGFzLm51bWVyaWMoZnlsa2UpID09IDMgfiAiT3NsbyIsCiAgICAgICAgICAgIGFzLm51bWVyaWMoZnlsa2UpICVpbiUgYygxOjIsIDQ6OCkgfiAiw5hzdGxhbmRldCIsCiAgICAgICAgICAgIGFzLm51bWVyaWMoZnlsa2UpICVpbiUgYyg5LCAxMCkgfiAiU8O4cmxhbmRldCIsCiAgICAgICAgICAgIGFzLm51bWVyaWMoZnlsa2UpICVpbiUgYygxMSwgMTIsIDE0LCAxNSkgfiAiVmVzdGxhbmRldCIsCiAgICAgICAgICAgIGFzLm51bWVyaWMoZnlsa2UpICVpbiUgYygxNiwgMTcpIH4gIlRyw7huZGVsYWciLAogICAgICAgICAgICBhcy5udW1lcmljKGZ5bGtlKSAlaW4lIGMoMTgsIDE5LCAyMCkgfiAiTm9yZC1Ob3JnZSIKICAgICAgICApCiAgICApICU+JSAKICAgIGdyb3VwX2J5KGRhdG8sIHJlZ2lvbikgJT4lIAogICAgc3VtbWFyaXNlKAogICAgICAgIHdmX0tfciA9IHN1bSh3Zl9LX2YsIG5hLnJtID0gVFJVRSksCiAgICAgICAgd2ZfTV9yID0gc3VtKHdmX01fZiwgbmEucm0gPSBUUlVFKSwKICAgICAgICB3Zl9LTV9yID0gd2ZfS19yICsgd2ZfTV9yLAogICAgICAgIGJlZl9LX3IgPSBzdW0oYmVmX0tfZiwgbmEucm0gPSBUUlVFKSwKICAgICAgICBiZWZfTV9yID0gc3VtKGJlZl9NX2YsIG5hLnJtID0gVFJVRSksCiAgICAgICAgYmVmX0tNX3IgPSBiZWZfS19yICsgYmVmX01fcgogICAgKSAlPiUgCiAgICBzZWxlY3QoZGF0bywgcmVnaW9uLCB3Zl9LX3IsIHdmX01fciwgd2ZfS01fciwgYmVmX0tfciwgYmVmX01fciwgYmVmX0tNX3IpCmBgYAoKUGxvdCBuw6UgZm9yIHJlZ2lvbmVuZSB3Zl9LTV9yL2JlZl9LTV9yLCBiw6VkZSB2aGEuIGdlb21fbGluZSgpIG9nIGdlb21fc21vb3RoKCkuIExhIGZhcmdlIHZpc2UgcmVnaW9uZW5lLiBTZXR0IGRlbm5lIGkgZ2dwbG90KCkgc2xpayBhdCBkZXQgZ2plbGRlciBmb3IgYsOlZGUgZ2VvbV9saW5lKCkgb2cgZ2VvbV9zbW9vdGgoKS4gU2V0dCBpIHRpbGxlZ2cgYWxwaGEgPSAwLjUgZm9yIGdlb21fbGluZSgpIG9nIHNlID0gRkFMU0UgZm9yIGdlb21fc21vb3RoKCkuIExlZ2cgdGlsIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSB0aWwgc2x1dHQgZm9yIMOlIGbDpSBsZWdlbmQgdW5kZXIgcGxvdHRldC4KCmBgYHtyfQojIGt2aW5uZXIgb2cgbWVubgp3Zl9yICU+JSAKICBnZ3Bsb3Qod2ZfciwgbWFwcGluZyA9IGFlcyh4ID0gZGF0bywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IHdmX0tNX3IvYmVmX0tNX3IsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSByZWdpb24pKSArCiAgZ2VvbV9saW5lKGFscGhhID0gMC41KSArCiAgZ2VvbV9zbW9vdGgoc2UgPSBGQUxTRSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgZ2d0aXRsZSgiQXJiZWlkc3N0eXJrZW5zIGFuZGVsIGF2IGJlZm9sa25pbmdlbiBmb3IgcmVnaW9uZW5lLiIpCmBgYAoKTGFnIHRpbHN2YXJlbmRlIHBsb3QgZm9yIGt2aW5uZXIuCgpgYGB7cn0KIyBrdmlubmVyCndmX3IgJT4lIAogIGdncGxvdCh3Zl9yLCBtYXBwaW5nID0gYWVzKHggPSBkYXRvLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gd2ZfS19yL2JlZl9LX3IsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSByZWdpb24pKSArCiAgZ2VvbV9saW5lKGFscGhhID0gMC41KSArCiAgZ2VvbV9zbW9vdGgoc2UgPSBGQUxTRSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgZ2d0aXRsZSgiQXJiZWlkc3N0eXJrZW5zIGFuZGVsIGF2IGJlZm9sa25pbmdlbiBmb3Iga3Zpbm5lciBwZXIgcmVnaW9uLiIpCmBgYAoKTGFnIHRpbHN2YXJlbmRlIHBsb3QgZm9yIG1lbm4KCmBgYHtyfQojIG1lbm4Kd2ZfciAlPiUgCiAgZ2dwbG90KHdmX3IsIG1hcHBpbmcgPSBhZXMoeCA9IGRhdG8sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSB3Zl9NX3IvYmVmX01fciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IHJlZ2lvbikpICsKICBnZW9tX2xpbmUoYWxwaGEgPSAwLjUpICsKICBnZW9tX3Ntb290aChzZSA9IEZBTFNFKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBnZ3RpdGxlKCJBcmJlaWRzc3R5cmtlbnMgYW5kZWwgYXYgYmVmb2xrbmluZ2VuIGZvciBtZW5uIHBlciByZWdpb24uIikKYGBgCgpGb3JsYXIga29ydCBkZW4gZ2VuZXJlbGxlIHV0dmlrbGluZ2VuIGkgYXJiZWlkc3N0eXJrZW4uIEh2YSBlciBkZXQgc29tIMKrcmVkZGVyIG9zc8K7PwoKRm9yIGt2aW5uZW5lIGthbiBlbiBzZSBhdCBkZXQgZXIgZW4gamV2bnQgw7hrZW5kZSB0cmVuZCBhdCBmbGVyZSBrdmlubmVyIGZyYSBhcmJlaWRzc3R5cmtlbiBqb2JiZXIuIERldCBrYW4gc2t5bGRlcyBmbGVyZSBncnVubmVyLCBtZW4gZW4gYXYgZGVtIGthbiB2w6ZyZSBrYW1wZW4gZm9yIGxpa2VzdGlsbGluZyBvZyBhdCBrdmlubmVuZSBza2FsIGFrdGl2dCBkZWx0YSBpIGpvYmJtYXJrZWRlbmUgb2cgaWtrZSBzbGlrIGRlIGdqb3JkZSBmw7hyLiBFbiBrYW4gc2UgYXQgZGUgaGFyIGVuIGxpdGVuIHV0ZmxhdGluZyBhdiBrdXJ2ZW4gaSAyMDA3LzIwMDggb2cgZGVuIGZhbGxlciBsaXR0IGV0dGVyIDIwMTEuIERlbiBmw7hyc3RlIHV0ZmxhdGluZ2VuIGthbiBza3lsZGVzIGZpbmFuc2tyaXNlbiBvZyBkZXQgc29tIGbDuHJ0ZSBtZWQgZGVyLCBtZW5zIGkgMjAxMSBrYW4gZGV0IHNreWxkZXMgYW5kcmUgdGluZy4gRW4ga2FuIHNlIGF0IGhvcyBtZW5uIHN5bmtlciBrdXJ2ZW4gaSBhbGxlIHJlZ2lvbmVuZSwgaSBub2VuIHJlZ2lvbmVyIG1lciBlbm4gYW5kcmUuIExpdHQgZmFyZ2VzdmFrLCBtZW4gdHJvciBkZXQgZXIgT3NsbyBzb20gcmVkZGVyIG9zcy4gRXZlbnR1ZWx0IFZlc3RsYW5kZXQuIAoKIyMgYG5lc3QoKWAgYXJibG9zCgpEYSBza2FsIHZpIGpvYmJlIGRpcmVrdGUgbWVkIGFyYmVpZHNsw7hzaGV0IG9nIGxhZ2UgbGluZcOmcmUgbW9kZWxsZXIgZm9yIGh2ZXIgYXYgZGUgNDE4IGtvbW11bmVuZS4gTW9kZWxsZW4gdmkgc2thbCBsYWdlIGVyIHDDpSBpbmdlbiBtw6V0ZSBwZXJmZWt0LiBWaSBlciBpbnRlcmVzc2VydCBpIHNlbHZlIHRla25pa2tlbiBtZWQgw6Ugb3JnYW5pc2VyZSBkYXRhZW5lIG9nIGtqw7hyZSBtb2RlbGxlciBww6UgbWFuZ2Ugc3Vic2V0dCBhdiBkYXRhZW5lIChoZXIgZm9yIGh2ZXIga29tbXVuZSkuCgpWaSB2aWwgc2UgcMOlIGVuIG1vZGVsbCBkZXIgdmkgZm9ya2xhcmVyIGFyYmVpZHNzdHlya2VuIGkgZW4ga29tbXVuZSB2aGEuIHVuZ2RvbXNsZWRpZ2hldCBvZyBsZWRpZ2hldCBibGFudCBsaXR0IGVsZHJlIGFyYmVpZHN0YWtlcmUgKDMwLTc0IMOlcikuIEVuIGh5cG90ZXNlIGVyIGF0IHZpIHZpbCBzZSBlbiBuZWdhdGl2IHNhbW1lbmhlbmcgbWVsbG9tIHVuZ2RvbXNsZWRpZ2hldCBvZyBhcmJlaWRzc3R5cmtlbi4gRGUgdW5nZSBmbHl0dGVyIGh2aXMgZGV0IGlra2UgZXIgam9iYi4KClZpIHN0YXJ0ZXIgbWVkIMOlIGdydXBwZXJlIHDDpSBrb21tdW5lIG9nIG5lc3QtZSBkYXRhZW5lLgoKYGBge3J9CmFyYmxvc19ieV9rbnIgPC0gYXJibG9zICU+JSAKICAgIGdyb3VwX2J5KGtuciwga25hdm4pICU+JSAKICAgIG5lc3QoKQpgYGAKCmBgYHtyfQpwcmludChhcmJsb3NfYnlfa25yLCBuID0gNCkKYXJibG9zX2J5X2tuciRkYXRhW1sxXV0KYGBgClZpIGhhciBuw6UgZW4gdGliYmxlIG1lZCBkYXRhIGZvciBodmVyIGtvbW11bmUgaW5uZSBpIHRpYmJsZS1lbiBhcmJsb3NfYnlfa25yLiAKClNrcml2IGVuIGZ1bmtzam9uIHNvbSBrasO4cmVyIGRlbiBsaW5lw6ZyZSBtb2RlbGxlbiB3Zl9LTSB+IGFscF8xNV8yOSArIGFscF8zMF83NCBww6UgZW4gaW5wdXQgZGF0YWZyYW1lIGFfZGYuIEthbGwgZnVua3Nqb25lbiBtb2QxIChpIG1hZ2VsIHDDpSBub2UgYmVkcmUgbmF2bikuCgpgYGB7cn0KbW9kMSA8LSBmdW5jdGlvbihhX2RmKXsKICBsbSh3Zl9LTSB+IGFscF8xNV8yOSArIGFscF8zMF83NCwgZGF0YSA9IGFfZGYpfQpgYGAKS0rDuHJlIHPDpSBtb2RlbGxlbiB2aGEuIGZ1bmtzam9uZW4gbW9kMSBww6UgZGF0YSBpIGFyYmxvc19ieV9rbnIsIG9nIGxhZyBlbiBsaXN0LWNvbHVtbiBpIGFyYmxvc19ieV9rbnIgc29tIGlubmVob2xkZXIgbW9kZWxsZW4uIEtqw7hyIG9nc8OlIHRpZHkgb2cgZ2xhbmNlIGZyYSBicm9vbSBww6UgbW9kZWxsZW5lIGZvciDDpSBmw6UgaGh2LiBrb2VmZmlzaWVudGVyIG9nIHVsaWtlIHN1bW1hcnkgYXYgbW9kZWxsZW4uIExhZ3JlIHJlc3VsdGF0ZW5lIGkgaGh2LiBtb2QxX2FyYmxvcywgbW9kMV9hcmJsb3NfY29lZiBvZyBtb2QxX2FyYmxvc19zdW0gKGkgc2lzdGUgZXIgc3VtIGZvcmtvcnRlbHNlIGZvciBzdW1tYXJ5KQoKYGBge3J9CmFyYmxvc19ieV9rbnIgPC0gYXJibG9zX2J5X2tuciAlPiUgCiAgICBtdXRhdGUobW9kMV9hcmJsb3MgPSBtYXAoZGF0YSwgLmYgPSBtb2QxKSkgJT4lCiAgICBtdXRhdGUobW9kMV9hcmJsb3NfY29lZiA9IG1hcChtb2QxX2FyYmxvcywgLmYgPSB0aWR5KSkgJT4lIAogICAgbXV0YXRlKG1vZDFfYXJibG9zX3N1bSA9IG1hcChtb2QxX2FyYmxvcywgLmYgPSBnbGFuY2UpKQphcmJsb3NfYnlfa25yW2FyYmxvc19ieV9rbnIka25yID09ICIwNDQxIixdW1szXV0KYGBgCgphcmJsb3NfYnlfa25yIHNrYWwgbsOlIHNlIHV0IHNsaWs6CgpgYGB7cn0KYXJibG9zX2J5X2tucgpgYGAKCiMjIyBLb21tdW5lc3TDuHJyZWxzZQoKVmkgbGFnZXIgb3NzIHPDpSBlbiBueSBrYXRlZ29yaSB2YXJpYWJlbCBmb3Iga29tbXVuZXN0w7hycmVsc2UuCgpgYGB7cn0Ka29tX3N0ciA8LSBiZWYgJT4lIAogICAgZmlsdGVyKGFhciA9PSAyMDE0KSAlPiUgCiAgICBtdXRhdGUoCiAgICAgICAga19zdHIgPSBjYXNlX3doZW4oCiAgICAgICAgICAgIGJlZl9LTSA8PSAyNTAwIH4gIlN2w6ZydCBsaXRlbiIsCiAgICAgICAgICAgIGJlZl9LTSA+IDI1MDAgJiBiZWZfS00gPD0gNjAwMCB+ICJMaXRlbiIsCiAgICAgICAgICAgIGJlZl9LTSA+IDYwMDAgJiBiZWZfS00gPD0gMjAwMDAgfiAiTWlkZGVscyIsCiAgICAgICAgICAgIGJlZl9LTSA+IDIwMDAwICYgYmVmX0tNIDw9IDYwMDAwIH4gIlN0b3IiLAogICAgICAgICAgICBiZWZfS00gPiA2MDAwMCAmIGJlZl9LTSA8PSAxMDAwMDAwIH4gIlN2w6ZydCBzdG9yIgogICAgICAgICkKICAgICkgJT4lIAogICAgc2VsZWN0KGtuciwga25hdm4sIGJlZl9LTSwga19zdHIpCmhlYWQoa29tX3N0cikKYGBgCgojIyMgUGFra2VyIHV0IG9nIGhlbnRlciBtb2RlbCBrYXJha3RlcmlzdGlrYQoKQnJ1ayBzw6UgdW5uZXN0KCkgdGlsIMOlIHBha2tlIHV0IG1vZDFfYXJibG9zX2NvZWYgb2cgbW9kMV9hcmJsb3NfY29lZiAoaHVzayBhdCBkZSB0byBtw6Ugc3TDpSBpIGVuIGMoKSBvZyBoYSBhbmbDuHJzZWxzdGVnbikuIFBsdWtrIHV0IHZhcmlhYmxlbmUga25yLCBrbmF2biwgdGVybSwgZXN0aW1hdGUsIHN0ZC5lcnJvciwgcC52YWx1ZS4uLjksIGFkai5yLnNxdWFyZWQgb2cgbGVnZyByZXN1bHRhdGV0IGkgbW9kX2FyYmxfcmUuCgpgYGB7cn0KI21vZGVsbCBhcmJlaWRzbMO4c2UgcmVzdWx0YXQKbW9kX2FyYmxfcmUgPC0gYXJibG9zX2J5X2tuciAlPiUgCiAgdW5uZXN0KGMoIm1vZDFfYXJibG9zX2NvZWYiLCAibW9kMV9hcmJsb3Nfc3VtIiksIG5hbWVzX3JlcGFpciA9ICJ1bml2ZXJzYWwiKSAlPiUgCiAgc2VsZWN0KGtuciwga25hdm4sIHRlcm0sIGVzdGltYXRlLCBzdGQuZXJyb3IsIHAudmFsdWUuLi45LCBhZGouci5zcXVhcmVkKQpgYGAKCkR1IHNrYWwgZGEgaGEgbm9lIHNvbSBzZXIgc2xpayB1dDoKCmBgYHtyfQpwcmludChtb2RfYXJibF9yZSwgbiA9IDEwKQpgYGAKClNsw6Ugc2FtbWVuIGtvbV9zdHIgb2cgbW9kX2FyYmxfcmUgdmhhLiBgbGVmdF9qb2luKClgLiBLYWxsIHJlc3VsdGF0ZXQgZm9yIGtvbV9zdHJfbW9kLgoKYGBge3J9CmtvbV9zdHJfbW9kIDwtIG1vZF9hcmJsX3JlICU+JSAKICAgIGxlZnRfam9pbihrb21fc3RyLCBieSA9IGMoImtuciIsICJrbmF2biIpKSAKYGBgCgpEYSBza2FsIGR1IGhhIG5vZSBzb20gc2VyIHNsaWsgdXQ6CgpgYGB7cn0KcHJpbnQoa29tX3N0cl9tb2QsIG4gPSA1KQpgYGAKClZpIHBsb3R0ZXIga29lZmZpc2llbnRlbmUgc29tIGVyIHNpZ25pZmlrYW50ZSBvZyBsYXIgZmFyZ2UgdmlzZSBrb21tdW5lIHN0w7hycmVsc2UuIFRhciB2ZWtrIGVrc3RyZW1lIGVzdGltYXQuCgpgYGB7cn0Ka29tX3N0cl9tb2QgJT4lIAogICAgZmlsdGVyKHRlcm0gPT0gImFscF8xNV8yOSIpICU+JSAKICAgIGZpbHRlcihlc3RpbWF0ZSA+IC01MDAgJiBlc3RpbWF0ZSA8IDUwMCApICU+JQogICAgZmlsdGVyKHAudmFsdWUuLi45IDwgMC4wNSkgJT4lIAogICAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoCiAgICAgICAgeCA9IGVzdGltYXRlLAogICAgICAgIHkgPSBwLnZhbHVlLi4uOSwKICAgICAgICBjb2xvdXIgPSBrX3N0cgogICAgICAgICkKICAgICAgICApICsKICAgIGdlb21fcG9pbnQoKQpgYGAKCkxhZyB0aWxzdmFyZW5kZSBwbG90IGZvciBhbHBfMzBfNzQuCgpgYGB7cn0Ka29tX3N0cl9tb2QgJT4lIAogICAgZmlsdGVyKHRlcm0gPT0gImFscF8zMF83NCIpICU+JSAKICAgIGZpbHRlcihlc3RpbWF0ZSA+IC01MDAgJiBlc3RpbWF0ZSA8IDUwMCApICU+JQogICAgZmlsdGVyKHAudmFsdWUuLi45IDwgMC4wNSkgJT4lIAogICAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoCiAgICAgICAgeCA9IGVzdGltYXRlLAogICAgICAgIHkgPSBwLnZhbHVlLi4uOSwKICAgICAgICBjb2xvdXIgPSBrX3N0cgogICAgICAgICkKICAgICAgICApICsKICAgIGdlb21fcG9pbnQoKQpgYGAKCkh2b3IgbWFuZ2UgaGFyIHZpPwoKYGBge3J9CmtvbV9zdHJfbW9kICU+JSAKICAgIGZpbHRlcih0ZXJtID09ICJhbHBfMTVfMjkiKSAlPiUgCiAgICBncm91cF9ieShrX3N0cikgJT4lIAogICAgc3VtbWFyaXNlKG4gPSBuKCkpCmBgYAoKYGBge3J9CmtvbV9zdHJfbW9kICU+JSAKICAgIGZpbHRlcih0ZXJtID09ICJhbHBfMTVfMjkiKSAlPiUgCiAgICBmaWx0ZXIoZXN0aW1hdGUgPiAtIDUwMCAmIGVzdGltYXRlIDwgNTAwICkgJT4lCiAgICBmaWx0ZXIocC52YWx1ZS4uLjkgPCAwLjA1KSAlPiUgCiAgICBncm91cF9ieShrX3N0cikgJT4lIAogICAgc3VtbWFyaXNlKG4gPSBuKCkpCmBgYAoKYGBge3J9CmtvbV9zdHJfbW9kICU+JSAKICAgIGZpbHRlcih0ZXJtID09ICJhbHBfMzBfNzQiKSAlPiUgCiAgICBmaWx0ZXIoZXN0aW1hdGUgPiAtIDUwMCAmIGVzdGltYXRlIDwgNTAwICkgJT4lCiAgICBmaWx0ZXIocC52YWx1ZS4uLjkgPCAwLjA1KSAlPiUgCiAgICBncm91cF9ieShrX3N0cikgJT4lIAogICAgc3VtbWFyaXNlKG4gPSBuKCkpCmBgYAoKYGBge3J9CmtvbV9zdHJfbW9kICU+JSAKICAgIGZpbHRlcih0ZXJtID09ICJhbHBfMTVfMjkiKSAlPiUgCiAgICBmaWx0ZXIocC52YWx1ZS4uLjkgPCAwLjA1KSAlPiUgCiAgICBncm91cF9ieShrX3N0cikgJT4lIAogICAgc3VtbWFyaXNlKG1lYW5fMTVfMjkgPSBtZWFuKGVzdGltYXRlKSkKYGBgCgpgYGB7cn0Ka29tX3N0cl9tb2QgJT4lIAogICAgZmlsdGVyKHRlcm0gPT0gImFscF8zMF83NCIpICU+JSAKICAgIGZpbHRlcihwLnZhbHVlLi4uOSA8IDAuMDUpICU+JSAKICAgIGdyb3VwX2J5KGtfc3RyKSAlPiUgCiAgICBzdW1tYXJpc2UobWVhbl8zMF83NCA9IG1lYW4oZXN0aW1hdGUpKQpgYGAKCmBgYHtyfQprb21fc3RyX21vZCAlPiUgCiAgICBmaWx0ZXIodGVybSA9PSAiYWxwXzE1XzI5IikgJT4lIAogICAgZmlsdGVyKHAudmFsdWUuLi45IDwgMC4wNSkgJT4lIAogICAgZ3JvdXBfYnkoa19zdHIpICU+JSAKICAgIHN1bW1hcmlzZShuID0gbigpKQpgYGAKICAKYGBge3J9CmtvbV9zdHJfbW9kICU+JSAKICAgIGZpbHRlcih0ZXJtID09ICJhbHBfMzBfNzQiKSAlPiUgCiAgICBmaWx0ZXIocC52YWx1ZS4uLjkgPCAwLjA1KSAlPiUgCiAgICBncm91cF9ieShrX3N0cikgJT4lIAogICAgc3VtbWFyaXNlKG4gPSBuKCkpCmBgYAoKSSBsaXR0IG92ZXIgNTAlIGF2IGtvbW11bmVuZSwgaG92ZWRzYWtsaWcgZGUgc23DpSwgc2VyIG1vZGVsbGVuIHV0IHRpbCB2aXJrZS4gS2Fuc2tqZSBub2Ugw6UgYnlnZ2UgdmlkZXJlIHDDpS4gIAoKYGBge3J9CiNzaXN0ZQpgYGAKCg==